﻿using System;
using System.Collections.Generic;
using System.Linq;
using ZilLion.Service.Core.DapperWrapper;
using ZilLion.Service.Core.Snowflake;
using ZilLion.Service.WeChatMall.Domain.Entitys.GsInfo;
using ZilLion.Service.WeChatMall.Domain.Repositorys.Interface.AppInfo;
using ZilLion.Service.WeChatMall.Domain.Repositorys.Interface.GoodInfo;
using ZilLion.Service.WeChatMall.Domain.Repositorys.Interface.ShopInfo;
using ZilLion.Service.WeChatMall.Domain.Responses.GsInfo;
using ZilLion.Service.WeChatMall.Domain.Services.Interface;

namespace ZilLion.Service.WeChatMall.Domain.Services
{
    public class GsService : IGsService
    {
        private readonly IAppGsRelationShipReponsitory _appGsRelationShipReponsitory;
        private readonly IGsBasicInfoRepository _gsBasicInfoRepository;
        private readonly IGsExtraInfoReponsitoty _gsExtraInfoReponsitoty;
        private readonly IGsGroupRelationShipReponsitory _gsGroupRelationShipReponsitory;
        private readonly IGsGroupReponsitory _gsGroupReponsitory;
        private readonly IOfflineGsRelationshipReponsitory _offlineGsRelationshipReponsitory;
        private readonly IOfflineGsReponsitory _offlineGsReponsitory;
        private readonly IShopGsRelationShipReponsitory _shopGsRelationShipReponsitory;

        public GsService(IGsBasicInfoRepository gsBasicInfoRepository, IGsExtraInfoReponsitoty gsExtraInfoReponsitoty,
            IGsGroupRelationShipReponsitory gsGroupRelationShipReponsitory, IGsGroupReponsitory gsGroupReponsitory,
            IShopGsRelationShipReponsitory shopGsRelationShipReponsitory,
            IAppGsRelationShipReponsitory appGsRelationShipReponsitory,
            IOfflineGsRelationshipReponsitory offlineGsRelationshipReponsitory,
            IOfflineGsReponsitory offlineGsReponsitory)
        {
            _gsBasicInfoRepository = gsBasicInfoRepository;
            _gsExtraInfoReponsitoty = gsExtraInfoReponsitoty;
            _gsGroupRelationShipReponsitory = gsGroupRelationShipReponsitory;
            _gsGroupReponsitory = gsGroupReponsitory;
            _shopGsRelationShipReponsitory = shopGsRelationShipReponsitory;
            _appGsRelationShipReponsitory = appGsRelationShipReponsitory;
            _offlineGsRelationshipReponsitory = offlineGsRelationshipReponsitory;
            _offlineGsReponsitory = offlineGsReponsitory;
        }

        public IList<GsGroupEntity> GetGroupList(string zlcompanykey)
        {
            return _gsGroupReponsitory.GetGroups(zlcompanykey).ToList();
        }

        public GsGroupEntity SaveGroup(GsGroupEntity entity)
        {
            if (entity.GroupId == 0)
            {
                entity.GroupId = SnowflakeIdCreater.Instance().GetNextId();
                _gsGroupReponsitory.AddGsGroup(entity);
            }
            else
            {
                _gsGroupReponsitory.EditGsGroup(entity);
            }

            return _gsGroupReponsitory.GetGroupById(entity.GroupId);
        }

        public GsGroupEntity GetGroupById(long id)
        {
            return _gsGroupReponsitory.GetGroupById(id);
        }

        public void RemoveGroup(long id)
        {
            using (var unit = new UnitOfWork())
            {
                _gsGroupReponsitory.RemoveGsGroupById(id, unit);
                _gsGroupRelationShipReponsitory.RemoveRelationShipByGroupid(id, unit);
                unit.Complete();
            }
        }

        public IList<GsFrontTreeDto> GetFrontGsTree(long shopid)
        {
            var result = new List<GsFrontTreeDto>();
            var basics = _gsBasicInfoRepository.GetGsBasicInfoByShopid(shopid).ToList();
            var extras = _gsExtraInfoReponsitoty.GetGsExtraInfoByShopId(shopid).ToList();
            var groups = _gsGroupReponsitory.GetGroupsByShopid(shopid).ToList();
            var relations = _gsGroupRelationShipReponsitory.GetRelationByShopid(shopid).ToList();
            foreach (var relation in relations)
            {
                var first = result.FirstOrDefault(x => x.CategoryId == relation.GroupId);
                if (first != null)
                {
                    var basic = basics.FirstOrDefault(x => x.GsId == relation.GsId);
                    var extra = extras.FirstOrDefault(x => x.GsId == relation.GsId);
                    var gsdto = GsFrontDto.Convert(basic, extra);
                    gsdto.CategoryId = relation.GroupId;
                    first.Foods.Add(gsdto);
                }
                else
                {
                    var group = groups.FirstOrDefault(x => x.GroupId == relation.GroupId);
                    var dto = new GsFrontTreeDto
                    {
                        Name = group?.GroupName,
                        CategoryId = group?.GroupId ?? 0,
                        Type = group?.GroupType,
                        Foods = new List<GsFrontDto>()
                    };
                    var basic = basics.FirstOrDefault(x => x.GsId == relation.GsId);
                    var extra = extras.FirstOrDefault(x => x.GsId == relation.GsId);
                    var gsdto = GsFrontDto.Convert(basic, extra);
                    gsdto.CategoryId = relation.GroupId;
                    dto.Foods.Add(gsdto);
                    result.Add(dto);
                }
            }
            return result;
        }

        public GoodSetDto GetGsInfoDto(long gsid)
        {
            var basic = _gsBasicInfoRepository.GetGsEntityById(gsid);
            var extra = _gsExtraInfoReponsitoty.GetGsExtraInfoEntityById(gsid);

            return new GoodSetDto
            {
                BasicInfo = basic ?? new GsBasicInfoEntity(),
                ExtraInfo = extra ?? new GsExtraInfoEntity()
            };
        }

        public GoodSetDto SaveBasicGsInfo(GsBasicInfoEntity basic, GsGroupRelationShipEntity relastionShip)
        {
            var notNew = basic.GsId > 0;
            if (!notNew)
            {
                var newid = SnowflakeIdCreater.Instance().GetNextId();
                basic.GsId = newid;
                relastionShip.GsId = newid;
            }
            using (var unit = new UnitOfWork())
            {
                if (notNew)
                    _gsBasicInfoRepository.EditGs(basic, unit);
                else
                    _gsBasicInfoRepository.AddGs(basic, unit);
                _gsGroupRelationShipReponsitory.RemoveRelationShip(relastionShip, unit);
                _gsGroupRelationShipReponsitory.AddRelationShip(relastionShip, unit);
                unit.Complete();
            }
            var dto = GetGsInfoDto(basic.GsId);
            return dto;
        }

        public IList<GoodSetDto> GetGoodsByGroup(long groupid)
        {
            var basiclist = _gsBasicInfoRepository.GetGsBasicInfoByGroupid(groupid);
            var extralist = _gsExtraInfoReponsitoty.GetGsExtraInfoByGroupId(groupid).ToList();
            return (from basic in basiclist
                let extra = extralist.FirstOrDefault(x => x.GsId == basic.GsId) ?? new GsExtraInfoEntity()
                select new GoodSetDto {ExtraInfo = extra, BasicInfo = basic}).ToList();
        }

        public IList<GoodSetDto> GetAllGoods()
        {
            var basiclist = _gsBasicInfoRepository.GetAllgs();
            var extralist = _gsExtraInfoReponsitoty.GetAllgs();
            return (from basic in basiclist
                let extra = extralist.FirstOrDefault(x => x.GsId == basic.GsId) ?? new GsExtraInfoEntity()
                select new GoodSetDto {ExtraInfo = extra, BasicInfo = basic}).ToList();
        }

        public IList<GoodSetDto> GetGoodsByAppid(string appid)
        {
            var basiclist = _gsBasicInfoRepository.GetGsBasicInfoByAppId(appid);
            var extralist = _gsExtraInfoReponsitoty.GetGsExtraInfoByAppId(appid);
            return (from basic in basiclist
                let extra = extralist.FirstOrDefault(x => x.GsId == basic.GsId) ?? new GsExtraInfoEntity()
                select new GoodSetDto {ExtraInfo = extra, BasicInfo = basic}).ToList();
        }

        public IList<GoodSetDto> GetGoodsByShopid(long shopid)
        {
            var basiclist = _gsBasicInfoRepository.GetGsBasicInfoByShopid(shopid);
            var extralist = _gsExtraInfoReponsitoty.GetGsExtraInfoByShopId(shopid);
            return (from basic in basiclist
                let extra = extralist.FirstOrDefault(x => x.GsId == basic.GsId) ?? new GsExtraInfoEntity()
                select new GoodSetDto {ExtraInfo = extra, BasicInfo = basic}).ToList();
        }

        public void DeleteGood(long gsid)
        {
            using (var unit = new UnitOfWork())
            {
                _gsBasicInfoRepository.RemoveByGsid(gsid, unit);
                _gsExtraInfoReponsitoty.RemoveByGsid(gsid, unit);
                _gsGroupRelationShipReponsitory.RemoveByGsid(gsid, unit);
                _shopGsRelationShipReponsitory.RemoveByGsid(gsid, unit);
                _appGsRelationShipReponsitory.RemoveByGsid(gsid, unit);
                _offlineGsRelationshipReponsitory.DeleteRelationshipByOnlineGs(gsid, unit);
                unit.Complete();
            }
        }

        public IList<OfflineGsEntity> GetImportableGs(string zlcompanykey)
        {
            return _offlineGsReponsitory.GetImportableGs(zlcompanykey);
        }

        public void ImportOfflineGs(IList<OfflineGsEntity> entitys, string zlcompanykey, long updater, long groupId)
        {
            using (var unit = new UnitOfWork())
            {
                foreach (var entity in entitys)
                {
                    var newgsid = SnowflakeIdCreater.Instance().GetNextId();

                    _offlineGsRelationshipReponsitory.DeleteRelationshipByOfflineGs(entity.Gsid, zlcompanykey, unit);
                    _offlineGsRelationshipReponsitory.AddRelationship(new OfflineGsRelationshipEntity
                    {
                        Zlcompanykey = zlcompanykey,
                        OfflineGsId = entity.Gsid,
                        Updater = updater,
                        UpdatedTime = DateTime.Now.GetNowChinaTime(),
                        GsId = newgsid
                    }, unit);
                    _gsBasicInfoRepository.AddGs(new GsBasicInfoEntity
                    {
                        ZlCompanyKey = zlcompanykey,
                        GsId = newgsid,
                        Updater = updater,
                        UpdatedTime = DateTime.Now.GetNowChinaTime(),
                        GsDescription = entity.GsIndexCode,
                        GsIcon = string.Empty,
                        GsImage = string.Empty,
                        GsInfo = string.Empty,
                        GsName = entity.GsName,
                        GsPrice = 0
                    }, unit);
                    _gsGroupRelationShipReponsitory.AddRelationShip(new GsGroupRelationShipEntity
                    {
                        Updater = updater,
                        UpdatedTime = DateTime.Now.GetNowChinaTime(),
                        GroupId = groupId,
                        GsId = newgsid,
                        GsSn = 0
                    }, unit);
                    unit.Complete();
                }
            }
        }
    }
}